package com.nbsaas.boot;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

public class MD5Cracker {
    // 模拟彩虹表 - 实际应用中可能会从文件加载大量数据
    private static Map<String, String> rainbowTable = new HashMap<>();
    
    static {
        // 预先计算一些常见字符串的MD5值存入彩虹表
        rainbowTable.put(md5("123456"), "123456");
        rainbowTable.put(md5("password"), "password");
        rainbowTable.put(md5("admin"), "admin");
        rainbowTable.put(md5("111111"), "111111");
        rainbowTable.put(md5("000000"), "000000");
        // 可以添加更多常见字符串及其MD5值
    }
    
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.print("请输入要破解的MD5值: ");
        String targetMd5 = scanner.nextLine().trim();
        
        // 从彩虹表中查找匹配
        String result = rainbowTable.get(targetMd5);
        
        if (result != null) {
            System.out.println("找到匹配的明文: " + result);
        } else {
            System.out.println("在彩虹表中未找到匹配的明文，尝试暴力破解...");
            // 尝试简单的暴力破解（仅作示例，实际效率极低）
            result = bruteForceCrack(targetMd5, 20); // 尝试4位数字密码
            if (result != null) {
                System.out.println("暴力破解成功: " + result);
            } else {
                System.out.println("破解失败，未找到匹配的明文");
            }
        }
        
        scanner.close();
    }
    
    /**
     * 计算字符串的MD5哈希值
     */
    public static String md5(String input) {
        if (input == null) {
            return null;
        }
        
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] messageDigest = md.digest(input.getBytes());
            
            // 将字节数组转换为十六进制字符串
            StringBuilder sb = new StringBuilder();
            for (byte b : messageDigest) {
                sb.append(String.format("%02x", b & 0xff));
            }
            return sb.toString();
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
    }
    
    /**
     * 简单的暴力破解方法，尝试指定长度的数字组合
     */
    public static String bruteForceCrack(String targetMd5, int length) {
        // 生成所有可能的数字组合
        int max = (int) Math.pow(10, length) - 1;
        for (int i = 0; i <= max; i++) {
            // 格式化数字，确保长度一致（例如：3 -> "0003" 当length=4时）
            String candidate = String.format("%0" + length + "d", i);
            String candidateMd5 = md5(candidate);
            
            if (targetMd5.equalsIgnoreCase(candidateMd5)) {
                return candidate;
            }
            
            // 每10000次尝试输出一次进度
            if (i % 10000 == 0) {
                System.out.println("已尝试 " + i + " 种组合...");
            }
        }
        return null;
    }
}
